package com.zhuoyue.biz.core.api.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuoyue.biz.core.api.dao.*;
import com.zhuoyue.biz.core.api.domain.*;
import com.zhuoyue.biz.core.api.domain.home.HomeFistReqDO;
import com.zhuoyue.biz.core.api.dto.rep.GatewayRepDTO;
import com.zhuoyue.biz.core.api.dto.rep.HomeRepDTO;
import com.zhuoyue.biz.core.api.dto.req.HomeReqDTO;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * @author wjming
 * @ClassName: HomeService
 * @Description: 家庭信息的增删改查
 * @Date 2021-06-30 17:33
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class HomeService extends ServiceImpl<HomeDao, HomeDO> {
    private final HomeDao homeDao;
    private final AppUserHomeRelationService relationService;
    private final GatewayDao gatewayDao;
    private final RoomService roomService;
    private final ProductInfoAppService productInfoAppService;
    private final LocalSceneService localSceneService;
    private final EzvizTokenService ezvizTokenService;

    /**
     * 1.4.0以前的版本
     *
     * @param home
     * @param appUserId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean addHome(HomeDO home, String appUserId) {
        //添加家庭
        saveHome(home);
        //添加用户与家庭之间的关系
        relationService.saveUserAndHomeRelation(home, appUserId);
        //添加该家庭下的默认房间
        roomService.addDefaultThreeRooms(home.getId());
        //添加该家庭下的默认场景
        localSceneService.createTwoNullScenes(home.getId());

        return true;
    }

    /**
     * @param home
     * @param appUserId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HomeRepDTO addHomeAndRepDTO(HomeDO home, String appUserId) {
        //添加家庭
        saveHome(home);
        //添加用户与家庭之间的关系
        relationService.saveUserAndHomeRelation(home, appUserId);
        //添加该家庭下的默认房间
        roomService.addDefaultThreeRooms(home.getId());
        //添加该家庭下的默认场景
        localSceneService.createTwoNullScenes(home.getId());
        HomeRepDTO homeRepDTO = new HomeRepDTO().homeDoToHomeRepDto(home);
        return homeRepDTO;
    }

    /**
     * 获取用户的家庭、网关、房间信息
     * 1、如果家庭不存在，添加一个空家庭，直接返回
     * 2、家庭存在，查询家庭、网关、房间、以及家庭中的一些设备信息并且返回
     *
     * @param appUserId
     * @return
     */
    public List<HomeRepDTO> getHome(String appUserId) {
        List<HomeFistReqDO> homeFistReqDO = homeDao.selectHomeFistReqDo(appUserId);
        if (CollectionUtils.isEmpty(homeFistReqDO)) {
            return giveUsersOneFamily(appUserId);
        }
        return getHomeGatewayAndRepHomeRepDTO(homeFistReqDO);
    }

    /**
     * 有萤石摄像头的家庭不能直接删除
     *
     * @param homeId
     * @param orgCode
     */
    public void deleteHomeById(String appUserId, String homeId, String orgCode) {
        int homeCount = relationService.count(Wrappers.<AppUserHomeRelationDO>lambdaQuery()
                .eq(AppUserHomeRelationDO::getAppUserId, appUserId).eq(AppUserHomeRelationDO::getRelationType, 0));
        if (homeCount <= 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "您至少需要留下一个主家庭");
        }

        int homeDeviceCount = homeDao.getHomeDeviceCount(homeId);
        if (homeDeviceCount > 0) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "请检查网关、摄像头、红外、wifi、摄像头等设备是否已删除");
        }

        ezvizTokenService.removeRemoteEz(homeId, orgCode);
        ezvizTokenService.remove(Wrappers.<EzvizTokenDO>lambdaQuery()
                .eq(EzvizTokenDO::getHomeId, homeId));
        // 删除家庭
        int count = homeDao.deleteById(homeId);
        if (count < 1) {
            throw new ZyServerException(ErrorType.REMOVE_ERROR);
        }

    }


    /**
     * 如果用户的家庭信息为空,给用户一个家庭
     *
     * @param appUserId
     * @return
     */
    private List<HomeRepDTO> giveUsersOneFamily(String appUserId) {
        List<HomeRepDTO> homeReps = new ArrayList<>();
        HomeReqDTO homeReqDTO = new HomeReqDTO();
        homeReqDTO.setName("小e的家");
        homeReqDTO.setImgUrl("home_01");
        HomeDO homeDo = new HomeDO().homeReqDtoToHomeDo(homeReqDTO);
        addHome(homeDo, appUserId);
        HomeRepDTO homeRepDTO = new HomeRepDTO().homeDoToHomeRepDto(homeDo);
        homeReps.add(homeRepDTO);
        return homeReps;
    }

    /**
     * 获取家庭中网关信息，并且返回家庭对象信息
     *
     * @param homeFistReqDO
     * @return
     */
    private List<HomeRepDTO> getHomeGatewayAndRepHomeRepDTO(List<HomeFistReqDO> homeFistReqDO) {
        List<HomeRepDTO> homeReps = new ArrayList<>();
        List<String> idList = homeFistReqDO.stream().map(home -> home.getGatewayId()).collect(Collectors.toList());
        List<GatewayDO> gateways = gatewayDao.selectBatchIds(idList);

        for (HomeFistReqDO homeFist : homeFistReqDO) {
            List<GatewayRepDTO> gatewayDos = new ArrayList<>(1);
            // 获取网关
            gateways.forEach(gateway -> {
                if (StringUtils.equals(gateway.getId(), homeFist.getGatewayId())) {
                    gateway.setHomeId(homeFist.getId());
                    List<String> deviceFun = productInfoAppService.getDeviceFun(gateway.getProdId());
                    GatewayRepDTO gatewayRepDTO = new GatewayRepDTO().gatewayDoToDto(gateway, deviceFun);
                    gatewayDos.add(gatewayRepDTO);
                }
            });
            HomeRepDTO homeRepDTO = new HomeRepDTO().homeFistReqDoToHomeRepDto(homeFist, gatewayDos);
            homeRepDTO.setGatewayList(gatewayDos);
            homeReps.add(homeRepDTO);
        }
        return homeReps;
    }


    /**
     * 通过Homeid查询家庭名称 (non-Javadoc)
     *
     * @param homeId
     * @return 家庭名称
     */
    public String getHomeNameById(String homeId) {
        String homeName = homeDao.selectHomeNameByHomeId(homeId);
        return homeName;
    }


    /**
     * 添加家庭
     *
     * @param home
     */
    private void saveHome(HomeDO home) {
        boolean count = save(home);
        if (!count) {
            throw new ZyServerException(ErrorType.SAVE_ERROR);
        }
    }
}
